package configuration.options;


import java.util.ArrayList;




import qxtract.model.DocumentHandle;
import qxtract.model.Rule;
import qxtract.weka.RipperBasedLearning;
import database.mediator.MediatorInterface;
import distributedRE.DistributedRE;
import distributedRE.model.DataBase;
import distributedRE.model.DistributedREModel;
import distributedRE.model.Document;
import distributedRE.model.Query;
import distributedRE.model.Session;
import documentsampler.DocumentSampler;

public class QXtractRetrain extends AdjustmentOption{


	private int K;

	private DocumentSampler ds;
	private long seed;
	private boolean use_prunning;
	private double min_no;
	private int optimizations;
	private int folds;
	private boolean check_error_rate;
	private ArrayList<String> pos;
	private ArrayList<String> neg;
	private int times;
	private String stopWordsFile;

	private String newName;

	private String relation;

	private String table;

	public QXtractRetrain(int K,  int folds, double min_no, int optimizations, long seed, boolean use_prunning, boolean check_error_rate, DocumentSampler ds,String stopWordsFile, String newName, String relation, String table) {
	
		super(3,K);
	
		this.folds = folds;
		this.min_no = min_no;
		this.optimizations = optimizations;
		this.seed = seed;
		this.use_prunning = use_prunning;
		this.check_error_rate = check_error_rate;
		this.stopWordsFile = stopWordsFile; 
		this.ds = ds;
		this.newName = newName;
		this.relation = relation;
		this.table = table;
		times = 0;
	}

	@Override
	protected void adapt(DistributedREModel dREModel, Session s, MediatorInterface mI) {
		
		times++;
		
		ArrayList<Document> badsampleDocs = ds.getBadSample(dREModel);
		
		ArrayList<Document> goodsampleDocs = ds.getGoodSample(dREModel);
		
		RipperBasedLearning ripper = new RipperBasedLearning(stopWordsFile,relation);
	    
		ArrayList<DocumentHandle> useful = new ArrayList<DocumentHandle>();
	    
	    ArrayList<DocumentHandle> sample = new ArrayList<DocumentHandle>();
	    
	    for (Document document: badsampleDocs) {
			
	    	sample.add(generateDocumentHandle(document));
		}
	    
	    for (Document goodsample : goodsampleDocs) {
			
	    	DocumentHandle dh = generateDocumentHandle(goodsample);
	    	
	    	sample.add(dh);
	    	
	    	useful.add(dh);
	    	
		}
	    
	   ripper.learn(sample, useful,new String(DistributedRE.FOLDER + "retrainer" + times + ".arff"),null,newName,false,false,null,null);
	
	   Rule[] rules = ripper.generateRules(folds,min_no,optimizations,seed,use_prunning,check_error_rate);
	   
	   generateQueries(rules,dREModel,mI);
		    
	}

	private ArrayList<Query> generateQueries(Rule[] rules, DistributedREModel dREModel, MediatorInterface mI) {
		
		long nextId;
		
		ArrayList<Query> ret = new ArrayList<Query>();
		
		for (Rule rule : rules) {
			
			if (rule.isPositive()){
				
				pos = rule.getPositiveAntecedent();
				neg = rule.getNegativeAntecedent();
				
				if ((pos.size() == 0) && (neg.size()==0)){
					continue;
				}
				
				String text = "";
				
				for (String term : pos){
					text += " +" + term;
				}
				
				for (String term : neg){
					text += " -" + term;
				}
				
				nextId = mI.getNextQueryId();
				
				Query q = new Query(nextId, text.trim(), Long.parseLong(dREModel.getInformationExtractor().getId()), dREModel.getRelation().getId());
				
				mI.writeQuery(q.getId(), q.getText(),  new Long(dREModel.getInformationExtractor().getId()).toString(),new Long(dREModel.getRelation().getId()).toString());
				
				if (nextId == mI.getNextDocumentId()){ //Not added to QueryTable
					continue;
				}
				
				dREModel.addQuery(q);
								
				for (DataBase database : dREModel.getDatabases()) {

					double ip = rule.getTruepositives() / (rule.getTruepositives() + rule.getFalsepositives());
					
					dREModel.setQueryForDataBase(q, database, ip);
					
					mI.writeInitialPrecision(q.getId(), database.getId(), ip);
					
				}
				
				
			}
			
		}
		
		return ret;
	}

	private DocumentHandle generateDocumentHandle(Document document) {
		
		return new DocumentHandle(document.getPath());
		
	}

	public String toString(){
		return "QXtract Retrain after " + K + " Steps";
	}
	
}
